﻿#include"stdafx.h"
#ifdef LK_MOBJECT_
namespace LK
{
	PType IMObject::GetType()const { return PType::Make<PMObjects>(); }
	/**
	@brief 获取内部类型*/
	PType IMObject::GetInnerType()const { return (PType const&)innerDataType; }
	/**
	@brief 获取封箱数据类型*/
	PType PMObjects::GetInnerType()const { return Ptr()->GetInnerType(); }
	void PMObjects::AddTypeInfo()
	{
#ifdef LK_REFLECTION_
		using namespace Reflection;
		using namespace Functional;
		//获取全局命名空间
		PNamespaceNode space = GetGlobleLibrary().GetGlobleNamespaceRef().FindOrAddNamespace(L"LK");
		//查找或添加PTime类型节点
		PTypeNode node = space.FindOrAddTypeNode(L"PMObjects", PType::Make<PMObjects>());
		//设置继承关系
		node.AddBaseType(PType::Make<PObject>());
#endif
	}
	/**
	@brief 获取内部数据指针，该方法常用以直接修改引用型封箱*/
	void*PMObjects::GetDataPtr()const { return Ptr()->GetDataPtr(); }
	bool PMObjects::IsCopy()const { return Ptr()->IsCopy(); }
	/**
	@brief 获取所表示的对象的指针，该方法常用以获取对象数值*/
	void*PMObjects::GetObjectPtr()const { return Ptr()->GetObjectPtr(); }
	void* IMObject::GetObjectPtr()
	{
		if (!innerDataType.IsNull())
		{
			if (GetInnerType().IsArray() || GetInnerType().IsLValueReference() || (GetInnerType().IsFunction() && GetInnerType().GetID() == 0))
				return *(void**)GetDataPtr();//存的地址，需要解引用
		}
		return GetDataPtr();//存的副本
	}
	//获取
#define _TMP(t) case t+(sizeof(size_t)>4):x = new MObject<(1ull<<(t+(sizeof(size_t)>4))) - sizeof(MObject <0>) - 4 * sizeof(size_t)>();break;
	PMObjects PMObjects::MakeMObjectByTypeInfo(PType const&t, const void* p)
	{
		PMObjects x;
		if (t == PType::Make<void>())return x;
		switch (sizeof(size_t) * 8 - Bits::LeftZeroCount((size_t)(t.GetSize() + sizeof(MObject <0>) + 5 * sizeof(size_t) - 1)))
		{
			MF3_RepeatAsc(_TMP, 5, 30);
		default:break;
		}
		x.Ptr()->innerDataType = t;
		if (p)t.CopyConstruct(x.GetDataPtr(), p);
		else t.DefaultConstruct(x.GetDataPtr());
		return x;
	}
	PMObjects PMObjects::MakeMObjectByTypeInfo(const void*pobj, PType const&t)
	{
		if (!pobj)throw PPointerIsNullException();
		if (!t.IsLValueReference())return MakeMObjectByTypeInfo(t, pobj);
		PMObjects x;
		switch (sizeof(size_t) * 8 - Bits::LeftZeroCount((size_t)(t.GetSizeIgnoreReference() + sizeof(void*) + sizeof(MObject <0>) + 5 * sizeof(size_t) - 1)))
		{
			MF3_RepeatAsc(_TMP, 5, 30);
		default:break;
		}
		x.Ptr()->innerDataType = t;
		t.CopyConstructIgnoreReference((u8*)x.GetDataPtr() + sizeof(void*), pobj);
		*(void**)x.GetDataPtr() = (*(void**)((u8*)x.GetDataPtr() - sizeof(void*))) = (u8*)x.GetDataPtr() + sizeof(void*);
		return x;
	}
	IMObject* IMObject::Clone()const { return PMObjects::MakeMObjectByTypeInfo(GetInnerType(), ((IMObject*)this)->GetDataPtr()).GetPtr(); }
	bool IMObject::IsCopy()const
	{
		if (((IMObject*)this)->GetDataPtr() && ((MObject<4>*)this)->ptmp)return true;
		return !GetInnerType().IsArray() && !GetInnerType().IsLValueReference() && !(GetInnerType().IsFunction() && GetInnerType().GetID() == 1);
	}

#undef _TMP
}
#endif